home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 11,000 to 11,999 / 11000.zip / AOLDLs / WIN Tools & Treiber / HELPDC21.exe / SPLITMRB.C < prev    next >
C/C++ Source or Header  |  1996-09-13  |  13KB  |  548 lines

  1. /*
  2. SPLITMRB - splits MRB into SHG/BMP/WMF and SHG into BMP/WMF files - Version 1.5
  3. M.Winterhoff, Geschw.-Scholl-Ring 17, 38444 Wolfsburg, Germany, CIS 100326,2776
  4.  
  5. usage: SPLITMRB filename[.mrb] ...
  6.        SPLITMRB filename.shg ...
  7.  
  8. Output files are created in the current directory using resolution-dependent
  9. extensions *.EGA,*.VGA,*.CGA,*.854,*.MAC or *.BMP,*.WMF or *.Snn,*.nnn (where
  10. n is a digit from 0 to 9). Discarded hotspot info will be written to stdout.
  11.  
  12. This program is freeware. Use at your own risk. No part of it may be used
  13. commercially. No fees may be charged on distributing.
  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18.  
  19. typedef enum {FALSE,TRUE} BOOL;
  20.  
  21. typedef struct tagBITMAPFILEHEADER
  22. {
  23.     unsigned short bfType;
  24.     unsigned long bfSize;
  25.     unsigned short bfReserved1;
  26.     unsigned short bfReserved2;
  27.     unsigned long bfOffBits;
  28. }
  29. BITMAPFILEHEADER;
  30.  
  31. typedef struct tagBITMAPINFOHEADER
  32. {
  33.     unsigned long biSize;
  34.     long biWidth;
  35.     long biHeight;
  36.     unsigned short biPlanes;
  37.     unsigned short biBitCount;
  38.     unsigned long biCompression;
  39.     unsigned long biSizeImage;
  40.     long biXPelsPerMeter;
  41.     long biYPelsPerMeter;
  42.     unsigned long biClrUsed;
  43.     unsigned long biClrImportant;
  44. }
  45. BITMAPINFOHEADER;
  46.  
  47. typedef struct tagRECT
  48. {
  49.     short left;
  50.     short top;
  51.     short right;
  52.     short bottom;
  53. }
  54. RECT;
  55.  
  56. typedef struct tagAPMFILEHEADER
  57. {
  58.     unsigned long dwKey;
  59.     unsigned short hMF;
  60.     RECT rcBBox;
  61.     unsigned short wInch;
  62.     unsigned long dwReserved;
  63.     unsigned short wChecksum;
  64. }
  65. APMFILEHEADER;
  66.  
  67. unsigned short GetCWord(FILE *f)
  68. {
  69.     unsigned char b;
  70.  
  71.     b=getc(f);
  72.     if(b&1) return (((unsigned short)getc(f)<<8)|(unsigned short)b)>>1;
  73.     return ((unsigned short)b>>1);
  74. }
  75.  
  76. unsigned long GetCDWord(FILE *f)
  77. {
  78.     unsigned short w;
  79.  
  80.     w = getw(f);
  81.     if(w&1) return (((unsigned long)getw(f)<<16)|(unsigned long)w)>>1;
  82.     return ((unsigned long)w>>1);
  83. }
  84.  
  85. unsigned long GetDWord(FILE *f)
  86. {
  87.     unsigned short w;
  88.  
  89.     w=getw(f);
  90.     return ((unsigned long)getw(f)<<16)|(unsigned long)w;
  91. }
  92.  
  93. long copy(FILE *f,long bytes,FILE *out)
  94. {
  95.     long length;
  96.     int size;
  97.     static char buffer[1024];
  98.  
  99.     for(length=0;length<bytes;length+=size)
  100.     {
  101.     size=(int)(bytes-length>sizeof(buffer)?sizeof(buffer):bytes-length);
  102.     fread(buffer,1,size,f);
  103.     fwrite(buffer,size,1,out);
  104.     }
  105.     return length;
  106. }
  107.  
  108. signed char count; /* for run len decompression */
  109.  
  110. int derun(int c,FILE *f) /* expand runlen compressed data */
  111. {
  112.     int i;
  113.  
  114.     if(count&0x7F)
  115.     {
  116.     if(count&0x80)
  117.     {
  118.         putc(c,f);
  119.         count--;
  120.         return 1;
  121.     }
  122.     for(i=0;i<count;i++)
  123.     {
  124.         putc(c,f);
  125.     }
  126.     count=0;
  127.     return i;
  128.     }
  129.     count=(signed char)c;
  130.     return 0;
  131. }
  132.  
  133. long decompress(int method,FILE *f,long bytes,FILE *fTarget)
  134. {
  135.     static unsigned char lzbuffer[0x1000];
  136.     int (*Emit)(int c,FILE *f);
  137.     unsigned char bits,mask;
  138.     int pos,len,back;
  139.     long n;
  140.  
  141.     n=0;
  142.     if(method&1)
  143.     {
  144.     Emit=derun;
  145.     count=0;
  146.     }
  147.     else
  148.     {
  149.     Emit=fputc;
  150.     }
  151.     if(method&2)
  152.     {
  153.     mask=0;
  154.     pos=0;
  155.     while(bytes-->0L)
  156.     {
  157.         if(!mask)
  158.         {
  159.         bits=getc(f);
  160.         mask=1;
  161.         }
  162.         else
  163.         {
  164.         if(bits&mask)
  165.         {
  166.             if(bytes--==0) break;
  167.             back=getw(f);
  168.             len=((back>>12)&15)+3;
  169.             back=pos-(back&0xFFF)-1;
  170.             while(len-->0)
  171.             {
  172.             n+=Emit(lzbuffer[pos++&0xFFF]=lzbuffer[back++&0xFFF],fTarget);
  173.             }
  174.         }
  175.         else
  176.         {
  177.             n+=Emit(lzbuffer[pos++&0xFFF]=getc(f),fTarget);
  178.         }
  179.         mask<<=1;
  180.         }
  181.     }
  182.     }
  183.     else
  184.     {
  185.     while(bytes-->0L) n+=Emit(getc(f),fTarget);
  186.     }
  187.     return n;
  188. }
  189.  
  190. int GetPackedByte(FILE *f) // RulLen decompression
  191. {
  192.     static unsigned char count,value;
  193.  
  194.     if(!f) // initialize
  195.     {
  196.     count=value=0;
  197.     }
  198.     else
  199.     {
  200.     if((count&0x7F)==0)
  201.     {
  202.         count=getc(f);
  203.         value=getc(f);
  204.     }
  205.     else if(count&0x80)
  206.     {
  207.         value=getc(f);
  208.     }
  209.     count--;
  210.     }
  211.     return value;
  212. }
  213.  
  214. void PrintHotspotInfo(FILE *f)
  215. {
  216.     int i,l,n;
  217.     typedef struct
  218.     {
  219.     unsigned char c1,c2,c3;
  220.     unsigned int x,y,w,h;
  221.     unsigned long hash;
  222.     }
  223.     HOTSPOT;
  224. #if sizeof(HOTSPOT)!=15
  225. #error Compile byte aligned !
  226. #endif
  227.     HOTSPOT *hotspot;
  228.     char name[80];
  229.     char buffer[128];
  230.  
  231.     if(getc(f)==1)
  232.     {
  233.     n=getw(f);
  234.     if(n>0)
  235.     {
  236.         hotspot=malloc(n*sizeof(HOTSPOT));
  237.         if(hotspot)
  238.         {
  239.         l=getw(f); // macro data size
  240.         getw(f);   // hiword ignored
  241.         fread(hotspot,sizeof(HOTSPOT),n,f);
  242.         for(i=0;i<l;i++) getc(f);
  243.         for(i=0;i<n;i++)
  244.         {
  245.             for(l=0;l<sizeof(name)&&(name[l]=getc(f))!='\0';l++);
  246.             for(l=0;l<sizeof(buffer)&&(buffer[l]=getc(f))!='\0';l++);
  247.             printf("'%s' ",buffer);
  248.             if((hotspot[i].c1&0xF0)==0xC0)
  249.             {
  250.             printf("Macro ");
  251.             }
  252.             else if(hotspot[i].c1&1)
  253.             {
  254.             printf("Jump ");
  255.             }
  256.             else
  257.             {
  258.             printf("Pop-up ");
  259.             }
  260.             if(hotspot[i].c2)
  261.             {
  262.             printf("Invisible");
  263.             }
  264.             else
  265.             {
  266.             printf("Visible ");
  267.             }
  268.             printf(" '%s' %d,%d,%d,%d\n",name,hotspot[i].x,hotspot[i].y,hotspot[i].x+hotspot[i].w,hotspot[i].y+hotspot[i].h);
  269.         }
  270.         free(hotspot);
  271.         }
  272.     }
  273.     }
  274. }
  275.  
  276. int main(int argc,char *argv[])
  277. {
  278.     FILE *f;
  279.     FILE *fTarget;
  280.     int i,j,k,l,m,n,colors;
  281.     unsigned char byType,byPacked;
  282.     long dwDataSize,dwHotspotOffset,dwHotspotSize,w,h,offset;
  283.     BITMAPFILEHEADER bmfh;
  284.     BITMAPINFOHEADER bmih;
  285.     APMFILEHEADER afh;
  286.     char filename[81];
  287.     BOOL res[7];
  288.  
  289.     if(argc<2)
  290.     {
  291.     fprintf(stderr,"SPLITMRB - splits MRB into SHG/BMP/WMF and SHG into BMP/WMF files - Version 1.5\n"
  292.                "M.Winterhoff, Geschw.-Scholl-Ring 17, 38444 Wolfsburg, Germany, CIS 100326,2776\n"
  293.                "\n"
  294.                "usage: SPLITMRB filename[.mrb] ...\n"
  295.                "       SPLITMRB filename.shg ...\n"
  296.                "\n"
  297.                "Output files are created in the current directory using resolution-dependent\n"
  298.                "extensions *.EGA,*.VGA,*.CGA,*.854,*.MAC or *.BMP,*.WMF or *.Snn,*.nnn (where\n"
  299.                "n is a digit from 0 to 9). Discarded hotspot info will be written to stdout.\n"
  300.                "\n"
  301.                "This program is freeware. Use at your own risk. No part of it may be used\n"
  302.                "commercially. No fees may be charged on distributing.\n");
  303.     }
  304.     else for(i=1;i<argc;i++)
  305.     {
  306.     strcpy(filename,argv[i]);
  307.     l=strlen(filename);
  308.     while(l>0&&filename[l-1]!='\\'&&filename[l-1]!='/'&&filename[l-1]!=':') l--;
  309.     m=l;
  310.     while(filename[l]!='\0'&&filename[l]!='.') l++;
  311.     if(filename[l]=='\0') strcpy(filename+l,".MRB");
  312.     f=fopen(filename,"rb");
  313.     if(!f)
  314.     {
  315.         fprintf(stderr,"Can not open '%s'\n",filename);
  316.     }
  317.     else
  318.     {
  319.         if((getw(f)&0xDFFF)!=0x506C)
  320.         {
  321.         fprintf(stderr,"'%s' is no MRB/SHG bitmap\n",argv[i]);
  322.         }
  323.         else
  324.         {
  325.         n=getw(f);
  326.         res[0]=res[1]=res[2]=res[3]=res[4]=res[5]=res[6]=FALSE;
  327.         for(j=0;j<n;j++)
  328.         {
  329.             fseek(f,4*(j+1),SEEK_SET);
  330.             fread(&offset,sizeof(offset),1,f);
  331.             fseek(f,offset,SEEK_SET);
  332.             byType=getc(f); // type of picture: 5=DDB, 6=DIB, 8=METAFILE
  333.             byPacked=getc(f); // packing method: 0=unpacked, 1=RunLen, 2=LZ77
  334.             if(byType==6||byType==5&&byPacked<2)
  335.             {
  336.             memset(&bmfh,0,sizeof(bmfh));
  337.             memset(&bmih,0,sizeof(bmih));
  338.             bmfh.bfType=0x4D42; // bitmap magic ("BM")
  339.             bmih.biSize=sizeof(bmih);
  340.             w=GetCDWord(f);
  341.             bmih.biXPelsPerMeter=(w*79L+1)/2;
  342.             h=GetCDWord(f);
  343.             bmih.biYPelsPerMeter=(h*79L+1)/2;
  344.             bmih.biPlanes=GetCWord(f);
  345.             bmih.biBitCount=GetCWord(f);
  346.             bmih.biWidth=GetCDWord(f);
  347.             bmih.biHeight=GetCDWord(f);
  348.             colors=(int)(bmih.biClrUsed=GetCDWord(f));
  349.             if(!colors) colors=1<<bmih.biBitCount;
  350.             bmih.biClrImportant=GetCDWord(f);
  351.             dwDataSize=GetCDWord(f);
  352.             dwHotspotSize=GetCDWord(f);
  353.             GetDWord(f); // dwPictureOffset
  354.             dwHotspotOffset=GetDWord(f);
  355.             if(dwHotspotOffset&&n>1) // dwHotspotOffset
  356.             {
  357.                 // save as SHG
  358.                 sprintf(filename+l,".S%02d",j);
  359.                 fTarget=fopen(filename+m,"wb");
  360.                 if(fTarget)
  361.                 {
  362.                 fprintf(stderr,"Extracting Segmented Hotspot Graphic '%s'...\n",filename+m);
  363.                 putw(0x506C,fTarget);
  364.                 putw(1,fTarget);
  365.                 putw(8,fTarget);
  366.                 putw(0,fTarget);
  367.                 fseek(f,offset,SEEK_SET);
  368.                 copy(f,dwHotspotOffset+dwHotspotSize,fTarget);
  369.                 fclose(fTarget);
  370.                 }
  371.                 else
  372.                 {
  373.                 fprintf(stderr,"Can not create '%s'\n",filename+m);
  374.                 }
  375.             }
  376.             else
  377.             {
  378.                 sprintf(filename+l,".%03d",j);
  379.                 if(w==96&&h==48&&!res[0])
  380.                 {
  381.                 strcpy(filename+l,".CGA");
  382.                 res[0]=TRUE;
  383.                 }
  384.                 else if(w==96&&h==72&&!res[1])
  385.                 {
  386.                 strcpy(filename+l,".EGA");
  387.                 res[1]=TRUE;
  388.                 }
  389.                 else if(w==96&&h==96&&!res[2])
  390.                 {
  391.                 strcpy(filename+l,".VGA");
  392.                 res[2]=TRUE;
  393.                 }
  394.                 else if(w==120&&h==120&&!res[3])
  395.                 {
  396.                 strcpy(filename+l,".854");
  397.                 res[3]=TRUE;
  398.                 }
  399.                 else if(w==72&&h==72&&!res[4])
  400.                 {
  401.                 strcpy(filename+l,".MAC");
  402.                 res[4]=TRUE;
  403.                 }
  404.                 else if(!res[6])
  405.                 {
  406.                 strcpy(filename+l,".BMP");
  407.                 res[6]=TRUE;
  408.                 }
  409.                 fTarget=fopen(filename+m,"wb");
  410.                 if(fTarget)
  411.                 {
  412.                 fprintf(stderr,"Extracting %ld x %ld x %u Bitmap '%s' (%ldx%ld dpi)...\n",bmih.biWidth,bmih.biHeight,bmih.biPlanes*bmih.biBitCount,filename+m,w,h);
  413.                 fwrite(&bmfh,1,sizeof(bmfh),fTarget);
  414.                 fwrite(&bmih,1,sizeof(bmih),fTarget);
  415.                 if(byType==6)
  416.                 {
  417.                     copy(f,colors*4L,fTarget);
  418.                 }
  419.                 else
  420.                 {
  421.                     long l;
  422.  
  423.                     l=0x000000L;
  424.                     fwrite(&l,1,sizeof(l),fTarget);
  425.                     l=0xFFFFFFL;
  426.                     fwrite(&l,1,sizeof(l),fTarget);
  427.                 }
  428.                 bmfh.bfOffBits=sizeof(bmfh)+sizeof(bmih)+colors*4L;
  429.                 bmih.biSizeImage=(((bmih.biWidth*bmih.biBitCount+31)/32)*4)*bmih.biHeight;
  430.                 if(byType==5) // convert 3.0 DDB to 3.1 DIB
  431.                 {
  432.                     long width,length,l;
  433.                     int pad;
  434.  
  435.                     width=((bmih.biWidth*bmih.biBitCount+15)/16)*2;
  436.                     pad=(int)(((width+3)/4)*4-width);
  437.                     GetPackedByte(NULL);
  438.                     for(l=0;l<bmih.biHeight;l++)
  439.                     {
  440.                     if(byPacked==1)
  441.                     {
  442.                         for(length=0;length<width;length++) putc(GetPackedByte(f),fTarget);
  443.                     }
  444.                     else
  445.                     {
  446.                         copy(f,width,fTarget);
  447.                     }
  448.                     if(pad) fwrite("    ",pad,1,fTarget);
  449.                     }
  450.                 }
  451.                 else
  452.                 {
  453.                     decompress(byPacked,f,dwDataSize,fTarget);
  454.                 }
  455.                 // update bitmap headers
  456.                 bmfh.bfSize=ftell(fTarget);
  457.                 fseek(fTarget,0L,SEEK_SET);
  458.                 fwrite(&bmfh,1,sizeof(bmfh),fTarget);
  459.                 fwrite(&bmih,1,sizeof(bmih),fTarget);
  460.                 fclose(fTarget);
  461.                 if(dwHotspotOffset)
  462.                 {
  463.                     fseek(f,offset+dwHotspotOffset,SEEK_SET);
  464.                     PrintHotspotInfo(f);
  465.                 }
  466.                 }
  467.                 else
  468.                 {
  469.                 fprintf(stderr,"Can not create '%s'\n",filename+m);
  470.                 }
  471.             }
  472.             }
  473.             else if(byType==8) // Windows MetaFile
  474.             {
  475.             APMFILEHEADER afh;
  476.             unsigned short *wp;
  477.  
  478.             memset(&afh,0,sizeof(afh));
  479.             afh.dwKey=0x9AC6CDD7L;
  480.             GetCWord(f); // mapping mode
  481.             afh.rcBBox.right=getw(f); // width of metafile-picture
  482.             afh.rcBBox.bottom=getw(f); // height of metafile-picture
  483.             GetCDWord(f);
  484.             dwDataSize=GetCDWord(f);
  485.             dwHotspotSize=GetCDWord(f); // dwHotspotSize
  486.             GetDWord(f); // dwPictureOffset
  487.             dwHotspotOffset=GetDWord(f);
  488.             if(dwHotspotOffset&&n>1) // dwHotspotOffset
  489.             {
  490.                 sprintf(filename+l,".S%02d",j);
  491.                 fTarget=fopen(filename+m,"wb");
  492.                 if(fTarget)
  493.                 {
  494.                 fprintf(stderr,"Extracting Segmented Hotspot Graphic '%s'...\n",filename+m);
  495.                 putw(0x506C,fTarget);
  496.                 putw(1,fTarget);
  497.                 putw(8,fTarget);
  498.                 putw(0,fTarget);
  499.                 fseek(f,offset,SEEK_SET);
  500.                 copy(f,dwHotspotOffset+dwHotspotSize,fTarget);
  501.                 fclose(fTarget);
  502.                 }
  503.                 else
  504.                 {
  505.                 fprintf(stderr,"Can not create '%s'\n",filename+m);
  506.                 }
  507.             }
  508.             else
  509.             {
  510.                 afh.wInch=2540;
  511.                 wp=(unsigned short *)&afh;
  512.                 for(k=0;k<10;k++) afh.wChecksum^=*wp++;
  513.                 if(!res[5])
  514.                 {
  515.                 strcpy(filename+l,".WMF");
  516.                 res[5]=TRUE;
  517.                 }
  518.                 else
  519.                 {
  520.                 sprintf(filename+l,".%03d",j);
  521.                 }
  522.                 fTarget=fopen(filename+m,"wb");
  523.                 if(fTarget)
  524.                 {
  525.                 fprintf(stderr,"Extracting Metafile '%s'...\n",filename+m);
  526.                 fwrite(&afh,1,sizeof(afh),fTarget);
  527.                 decompress(byPacked,f,dwDataSize,fTarget);
  528.                 fclose(fTarget);
  529.                 }
  530.                 if(dwHotspotOffset)
  531.                 {
  532.                 fseek(f,offset+dwHotspotOffset,SEEK_SET);
  533.                 PrintHotspotInfo(f);
  534.                 }
  535.             }
  536.             }
  537.             else
  538.             {
  539.             fprintf(stderr,"Picture %d of '%s' unknown type %02x pack=%02x skipped.\n",j,argv[i],byType,byPacked);
  540.             }
  541.         }
  542.         }
  543.         fclose(f);
  544.     }
  545.     }
  546.     return 0;
  547. }
  548.